use prost::Message;
use base64::prelude::*;
use photon_rs::transform::SamplingFilter;

mod abi;
pub use abi::*;

impl ImageSpec {
    pub fn new(specs: Vec<Spec>) -> Self {
        Self { specs }
    }
}

impl From<&ImageSpec> for String {
    fn from(value: &ImageSpec) -> Self {
        let data = value.encode_to_vec();
        BASE64_URL_SAFE_NO_PAD.encode(data)
    }
}

impl TryFrom<&str> for ImageSpec {
    type Error = anyhow::Error;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        let data = BASE64_URL_SAFE_NO_PAD.decode(value)?;
        Ok(ImageSpec::decode(&data[..])?)
    }
}

impl filter::Filter {
    /// 将过滤器类型转换为对应的字符串表示
    ///
    /// 此函数通过匹配不同的过滤器类型，返回相应的静态字符串引用
    /// 如果过滤器类型未指定，则返回None
    ///
    /// # Returns
    /// - `None`: 当过滤器类型为 `Unspecified`
    /// - `Some(&'static str)`: 返回与过滤器类型对应的字符串引用
    pub fn to_str(&self) -> Option<&'static str> {
        match self {
            // 未指定的过滤器类型，返回None
            filter::Filter::Unspecified => None,
            // 海洋型过滤器，返回"Some("oceanic")"
            filter::Filter::Oceanic => Some("oceanic"),
            // 岛屿型过滤器，返回"Some("islands")"
            filter::Filter::Islands => Some("islands"),
            // 海洋性气候过滤器，返回"Some("marine")"
            filter::Filter::Marine => Some("marine"),
        }
    }
}


impl From<resize::SampleFilter> for SamplingFilter {
    /// 将resize::SampleFilter类型转换为SamplingFilter类型
    ///
    /// # Parameters
    /// - `v`: resize::SampleFilter类型，表示图像处理中的采样过滤器类型
    ///
    /// # Return value
    /// 返回SamplingFilter类型，根据输入的resize::SampleFilter类型选择相应的过滤器类型
    ///
    /// # Description
    /// 此函数通过匹配输入的resize::SampleFilter类型，将图像处理中的采样过滤器类型转换为对应的SamplingFilter类型
    /// 它覆盖了所有可能的resize::SampleFilter类型，并提供了默认情况下的处理方式
    fn from(v: resize::SampleFilter) -> Self {
        match v {
            resize::SampleFilter::Undefined => SamplingFilter::Nearest,
            resize::SampleFilter::Nearest => SamplingFilter::Nearest,
            resize::SampleFilter::Triangle => SamplingFilter::Triangle,
            resize::SampleFilter::CatmullRom => SamplingFilter::CatmullRom,
            resize::SampleFilter::Gaussian => SamplingFilter::Gaussian,
            resize::SampleFilter::Lanczos3 => SamplingFilter::Lanczos3,
        }
    }
}

// 提供一些辅助函数，让创建一个 spec 的过程简单一些
impl Spec {
    /// 创建一个新的调整大小操作，使用接缝雕刻算法。
    ///
    /// 接缝雕刻是一种内容感知的图像调整大小技术，它可以在不破坏图像内容的情况下，改变图像的大小。
    /// 本函数主要用于初始化一个调整大小的操作，其中包含宽度、高度和调整大小的类型（接缝雕刻）。
    ///
    /// # 参数
    ///
    /// * `width` - 调整后的图像宽度。
    /// * `height` - 调整后的图像高度。
    ///
    /// # 返回值
    ///
    /// 返回一个包含调整大小信息的`Self`实例，其中`data`字段被填充为`Resize`结构体，
    /// 并设置了`width`、`height`和`rtype`（调整大小类型为接缝雕刻）。
    ///
    /// # 示例
    /// let resize_operation = Spec::new_resize_seam_carve(800, 600);
    ///
    pub fn new_resize_seam_carve(width: u32, height: u32) -> Self {
        Self {
            data: Some(spec::Data::Resize(Resize {
                width,
                height,
                rtype: resize::ResizeType::SeamCarve as i32,
                filter: resize::SampleFilter::Undefined as i32,
            }))
        }
    }
    pub fn new_resize(width: u32, height: u32, filter: resize::SampleFilter) -> Self {
        Self {
            data: Some(spec::Data::Resize(Resize {
                width,
                height,
                rtype: resize::ResizeType::Normal as i32,
                filter: filter as i32,
            }))
        }
    }
    /// 创建一个新的过滤器实例
    ///
    /// 此函数接受一个 `filter::Filter` 类型的参数，并将其转换为 `i32` 类型后，
    /// 封装到 `spec::Data::Filter` 结构中，最终返回一个包含该数据的当前类型实例。
    ///
    /// # 参数
    ///
    /// * `filter` - 一个 `filter::Filter` 类型的过滤器，用于定义过滤行为。
    ///
    /// # 返回值
    ///
    /// 返回一个当前类型的实例，其中包含提供的过滤器信息。
    pub fn new_filter(filter: filter::Filter) -> Self {
        Self {
            data: Some(spec::Data::Filter(Filter {
                filter: filter as i32
            }))
        }
    }
    /// 创建一个新的水印对象
    ///
    /// # 参数
    ///
    /// - `x`: 水印在横向的位置
    /// - `y`: 水印在纵向的位置
    ///
    /// # 返回值
    ///
    /// 返回一个带有水印的`Self`类型对象
    pub fn new_watermark(x: u32, y: u32) -> Self {
        Self {
            data: Some(spec::Data::Watermark(Watermark { x, y })),
        }
    }
}


#[cfg(test)]
mod tests {
    use super::*;
    use std::borrow::Borrow;
    use std::convert::TryInto;
    #[test]
    fn encoded_spec_could_be_decoded() {
        let spec1 = Spec::new_resize(600, 600, resize::SampleFilter::CatmullRom);
        let spec2 = Spec::new_filter(filter::Filter::Marine);
        let image_spec = ImageSpec::new(vec![spec1, spec2]);
        let s: String = image_spec.borrow().into();
        assert_eq!(image_spec, s.as_str().try_into().unwrap());
    }
}